User talk:SeravySensei
Archived discussions Hello from Beastorizer Hi Seravy. Your work on the 1.5 patch and Caster of Magic is much appreciated. I actually don't mind the new cameos, I figure I've got enough openness to experience to play 25 yr old DOS games so anime is no big deal. It's not even that weird, there is a nude pokemon total conversion mod for Sid Meier's Alpha Centauri after all. However, I've only watched ~20 anime in my time so I'm unable to recognize all these new characters. Would you mind making a list of: anime girl > MOM character they replace > what anime/game they are from Also, of the source anime which do you recommend watching? Thanks, Beastorizer (talk) 05:16, April 10, 2019 (UTC) Raise Dead Sorry, I'm opening this can of worms, but there's been way too many changes to the Raise Dead spell-cast function by both you and kyrub to make it viable for me to create a universal fix. So here's the list of issues, their current workarounds in the RC/CoM, if any, what I'd consider to be the proper solutions, and my comments: # The target array size is limited to 8. If there are more, we start overwriting stuff. Even in v1.31, you can get 9 targets here, so this is most certainly a problem. It is also untouched as of yet. The question is, how many targets should be allowed? The obvious answer is 36 + 1 (I'll get back to that in a minute), except that yields 37 * 2 * 2 = 148 bytes (2 word-sized arrays, one for the indices, one for the string pointers), which need an extra byte to address. For v1.31, I'll go for 16, would that be enough for you? # The strings in the string pointer array are being copied to instead of assigned to, leading to automatic memory corruption every time the spell is cast. Kyrub did an utterly horrible fix of this 6-byte problem by redirecting the strings to the area of the data segment that holds the sound error messages. Even if by some miracle you convinced me to let that slip, extending the array will overwrite the _atexitcnt static of borland, which will crash the game whenever you exit (including to MAGIC.EXE). Unfortunately, I think the space kyrub freed during this fix are being reused in one of yours dealing with un-involved units, but I might be mistaken there. # Un-involved units are considered valid targets. This was supposed to be a one-byte fix, the one I posted earlier, which you've also used everywhere else, except here. It makes adding the second check specifically for status 3 units redundant. # The string list parameter of the GUI_ListSelect_Dlg function expects the list to be terminated by a zero string, an issue that can cause extra buttons to appear on the list that, when clicked, will crash the game more often than not. This is where the +1 above comes from, although technically the index array doesn't need this. On the other hand, it needs to be dynamically set up, for which the best space I found is the branch just before the call. # Casting the spell causes the graphics to get distorted by replacing the original combat background screen image with the full combat screen image, which is then used until reset way out in the main combat function. You've created a partial fix for this by removing the call that saves the full image over the background one, but that only fixes the problem if the selection list is never shown, as it will do this again regardless. The proper fix here is to recompose the background image afterwards, which is something the dialog itself can not do, as it is also used for overland spells. We can do it very easily however, without even altering the relocation table. # The list selection dialog loads its control images into a memory area that is no longer valid after returning, causing the game to crash on the next page flip if the GUI is not cleared beforehand (by the way, this is the same issue that causes the Call Chaos AI-cast crash in v1.31 - you'll probably hate me for undoing your new graphics in the next few weeks, but I'll try to give you something special to compensate for that). Your current workaround is to just use the function without the scrolling capability. This is enough for displaying 10 units or so without breaking the graphics and possibly messing up the return value. This bug is easy to fix in the dialog function itself, which will automatically apply to all of the spells using it. Of course, in the end, you can decide to just leave everything as it is, it's a more or less valid standpoint, as the major crash bugs are fixed one way or another. Your AI target selector filters out the AI side bugs, which really leaves only the ones where the human player has a long list of units to raise. Also, this does not yet touch on Animate Dead, apart from fixing the dialog used by both. Do you want me to check which of these can be universally fixed and continue from there, create a small reversal patch and fix everything from the v1.31 code, or try to create a special version with only the fixes of your choice? My original fix for all of these involves around 45 bytes in the Raise Dead function and around 30 in the dialog. As far as I could tell the CoM and the RC code is the same in both regions, the AI target selection is resolved elsewhere and inserted into the tile randomizer space, so with a minimal reversal, I think nothing should be in the way. Drake178 (talk) 01:09, July 10, 2019 (UTC) 1. Actually the (not so) obvious answer is 9. Raise Dead targets self-owned normal units and you can at most have 9 of those, the rest of the slots can only ever have combat summons in them or belong to the enemy. This is true even for CoM in theory although I'm not sure I ever tested if the combat summoned "normal turned fantasic" units are properly excluded, they should be. This won't be so trivial for Animate Dead though which raises enemy and fantastic units as well. Also unsure what happens if a control changed unit dies, that might make it possible to have 18 valid targets instead of 9 if they stay on the new owner's side of the "graveyard". So 18 should be the 100% safe amount but I can't really imagine a combat where I possess 8 or more enemy units, they all die, and I'm STILL fighting that battle without either side winning AND Cast Raise Dead on top of it. (In fact you need the life+death mod to even do that unless all units died when confusion made them randomly change sides.) So I think 16 is good enough for this but Animate Dead will be different. 2. Yeah that sounds bad, it should be fixed. 3. I do have "3" excluded specifically in CoM, yes, doing >3 like you did it better. It probably ended this way because I copied the exclusion of 6 without noticing it already has a >0 earlier or maybe didn't know what 1 and 2 were for at that time. 6. Not really, I don't care much for the "new graphics" it was just a workaround for not being able to make the official one work. I admit I got used to it and it doesn't look bad at all, but it wasn't meant to be an important addition original. Looking forward to your alternate solution. As a side note, CoM's Call Chaos can't do "no effect", but can do "Confusion" instead so it is different. Another side note, in CoM in the "effect" part there are changes like zeroing more stuff on the raised unit, but those areas are likely not affected. I'd prefer one big patch file for all of this asuming you do want to spend time on fixing them all. I'll probably just write "fixes 6 different sources of crashes, memory or graphical corruptions in Raise Dead" in the patch file instead of trying to explain all that to users. But while we are at it, I have three more worms in the can left : 7. Raise Dead targets a random tile. I might like it this way better as it is more balanced for gameplay, but from a certain viewpoint this can be considered a bug? Is there any official source stating these revival spells cannot target a specific tile and also do not raise the dead unit where it actually died? Because one of those two would make sense, this does not and is unique, the only other thing that does it is Summon Demon which is an ability, not a spell at least in the RC. (random is good for game balance because it means you can't raise a unit and suicide it on a target to deal massive damage immediately the repeat - unless it can move a lot or have teleport or merging items in which case you can nonetheless. But it's not a big concern because CoM limits raising the same unit to only once per combat anyway.) 8. If you click outside the menu to cancel the spell, the cost is used up. This is unlike any other combat spell where cancelling without selecting a target spends nothing. Probably hard to fix but has actual unwanted game consequences if someone triggers it, and the worst part is, they might not even know clicking there cancels the spell, and it's fairly easy to do so by accident. 9. What happens to the movement of the unit? As far as I remember, the spell raises the unit with full movement but when I did the big CoM movement overhaul last week I didn't find where the movement is reset and I also don't think dead units reset it at end of turns. I'm not even sure what should happen? Get back the unit with the amount of moves it had left, but full if it died in an earlier turn, or have it at full even if it did move, die and revive in one turn? The CoM movement overhaul now resets it just to be on the safe side but no idea about the original. SeravySensei (talk) 02:11, July 10, 2019 (UTC) :7 and 8 are on my other list, because I can't immediately fix them from where I am. There is nothing in either the Spellbook supplement or the Official Strategy Guide that either explains, or even mentions the different targeting of these spells. It was also marked as a "bug" by Nodemaster, one of the contributors to the original gamefaqs guide, although I relegated it to a concept flaw instead. However, to be perfectly honest, I have a bit of a vision here, that if I can realize, I actually wouldn't care what the "canon" was in this particular case. :So here's what I imagined. You cast Raise Dead or Animate Dead. A shadow is cast over the battlefield, everything freezes, and the dead units that are valid targets suddenly appear as "spirits" of their former selves - mostly blue, but some of them red. This is your target picker. You can mouse over the units to get a tooltip, and if I'm really good, you may even be able to right-click them for stats (but I can't promise this one). For Raise Dead, multi-figure units appear with half the figures, as they would if brought back. :If you click on a blue unit, targeting is finished, the unit comes back on the tile it is on, and combat resumes. If you click on a red unit, you get a warning that the tile it died on is occupied, and if targeted, the unit will come back to a random tile, with a dialog asking if you wish to continue. You can then select "Yes", in which case the unit is summoned to a random tile, or "No" to get back to the target picker. You can also "Cancel" at the bottom right to exit without spending resources. :Now this may seem like it's outside the realm of possibility to you, but it isn't at all, the hardest part most likely being choosing (or creating) the right image effect (BU field 0x60 IIRC) for the spirits. For the rest, I just need some space, two or three functions, and a bunch of far calls. Implementing this would resolve both 7 and 8 in a very novel way, but it's unfortunately not something I can do until later on, so a temporary solution may be warranted in the meantime. :Which brings us to the random summoning. Since this would be required anyway, and because it's also used in other places, I'll probably start here as soon as I get to a state where I can tackle this issue. You see, this is also inherently bugged everywhere it is done. If all of the tiles in the 3×3 are occupied by units already, one of two things will happen. Half of the functions that use this feature will pop a unit on top of another one that's already there, while the other half will simply freeze in an infinite loop. :I would most certainly not want to fix this everywhere it occurs. It is much more desirable to create a separate function that takes an X and a Y return pointer along with a boolean for attacker/defender, and resolves the tile picking randomly if possible, or by, say, clockwise extension from the center if not. Or a 4×4 random. Or any other reasonable method that always yields a valid result. This function could then be called from all of the places where a random summon occurs. :The reason I didn't do anything about this yet is that I still don't have all the uses of the targeting map in sight, which is what all of these code blocks depend on. I know where and how it's filled out, but I don't know all of the whens, and there is also some contradicting stuff about the how. I'm reluctant to try to fix something when I can't see the whole picture yet. :Anyway, assume we go with the random for Raise Dead rather than the tile select for Animate Dead. At least, that would be my choice despite the little player ringing in my ear telling me that's the worse one. That means that for a start, the resolution of these spells should be altered. Namely, the selection should be performed when other spells do their target picking, and the actual spell-cast routine should only execute the animation and apply the effect. This way, it's the list selection that is cancelled during target picking, which yields a -1 in the main combat spell function, which resolves #8 automatically. :Since both spells have a separate function, we can probably reorganize them such that one will be the target picker for both, the other the execution for both. Otherwise, we have to build one or the other functionality into the existing combat spell routines. The ccc patch would probably allow this for the target picker in the RC through its combination of the resource expenditure branches, which should actually also be portable to CoM. However, separate functions would ultimately be desirable, especially if the first solution is going to be a temporary one for sure. :As for 9, I'll see if I can find that, I don't know off the top of my head either. EDIT: BU_SetBaseStats(), the generic stat (re-)calculator sets movement at $8F2B2. So it's always full movement. Drake178 (talk) 20:12, July 10, 2019 (UTC) : I should have realized but it's so counterintuitive my mind completely ignored that even though I had to disable it when fixing movement in CoM. I thought "that can't be there, it would reset the movement in the middle of the turn if the unit is ever recalculated" and that's exactly what it did in the CoM update at first. But in the original it's safe, but only because ALL stat recalculations also save and then restore the movement. SeravySensei (talk) 14:22, July 11, 2019 (UTC) Watching Hadriex's ongoing game reminded me there was another problem with the spell : auto combat opens the target menu even though it should not - auto combat means to ask for no user input at all. Instead it should either use the AI target, or select at random. SeravySensei (talk) 16:35, July 15, 2019 (UTC) Enchant Target Picker Yes, this is already excluded in CoM in the $81810 function. However 1.51 seems to have an older version of it which doesn't include magic immunty checks yet. I suggest modifying the CoM version of that procedure for compatibility (the issue is CoM has some spells added or removed, it isn't the space), this is the latest CoM source - do note due to space limitations, there might still be some restrictions implemented outside or not at all, but it at least covers most stuff : I'll fix the outside having 20h instead of the correct 8 for magic immunity enchantment, and I'd prefer if the check for the unit ability was done inside as it affects a lot more spells. ; in : ; di = battle unit ID ; bp+6 spell id ; bp-0Ah enchantments low ; bp-0Ch enchantments high ; out : ; dx = priority ; * 81810 ;------------------------------------------------- ; Prepare data ;------------------------------------------------- push si mov si,bp+6 ; si = spell mov ax,di mov dx, 6Eh ; 'n' imul dx les bx, 922Ah add bx, ax ; es:bx = unit offset test word ptr es:bx+22h,442h jnz invalid xor dx,dx ; return value = 0 ;------------------------------------------------- ; Gate Bonus ;------------------------------------------------- cmp word ptr es:bx+44h,8 jnz skip cmp word ptr es:bx+46h,12 jnz skip add dx,20 ; +20 to unit at gate skip: ;------------------------------------------------- ; Which spell? ;------------------------------------------------- ; Resist Elements cmp si,2 jz magimmun ; Don't if Magic Immunity ; Elemental Armor cmp si,15h jz magimmun ; Don't if Magic Immunity ; Iron Skin ;cmp si,18h ;jz prefhero ; Regeneration cmp si,1Fh jz regen ; Resist Magic cmp si,29h jz magimmun ; Don't if Magic Immunity ; Guardian Wind cmp si,2Ch jz guardian ; Flight cmp si,38h jz strongest ; Invisibility cmp si,3Eh jz prefranged ; Magic Immunity cmp si,45h jz magimmun ; Haste cmp si,4Dh jz strongest ; Eldritch Weapon cmp si,5Eh jz strongest ; Flame Blade cmp si,56h jz atkbuff ; Immolation cmp si,63h jz maxdef ;immolate ; Bless cmp si,79h jz magimmun ; Holy Weapon cmp si,7Ch jz atkbuff ; Holy Armor cmp si,7Eh jz maxdef ; Heroism cmp si,82h jz heroism ; True Sight cmp si,83h ; Don't if already Illusion Immune (no space) jz prefranged ; Lionheart ;cmp si,8Dh ;jz prefhero ; Invulnerability ;cmp si,8Fh ;jz prefhero ; Rightousness ;cmp si,90h ;jz prefhero ; Cloak of Fear ;cmp si,0A4h ;jz prefhero ; Berserk ;cmp si,0B3h ;jz berserk ; Wraith Form cmp si,0A8h jz wraithform jmp prefhero wraithform: test byte ptr es:bx+19h,1h jnz invalid ; Don't if already weapon immune! jmp prefhero ;immolate: ;NOT ENOGUH SPACE FOR THIS ;test byte ptr es:bx+1Ah,8h ;jnz invalid ; Don't if already immolating ;jmp maxdef regen: test byte ptr es:bx+1Dh,20h jnz invalid ; Don't if already regenerates jmp prefhero magimmun: test byte ptr es:bx+18h,20h jnz invalid ; Don't if already magic immune! jmp prefhero ;------------------------------------------------- heroism: mov ax, es:bx+30h mov cl, 5 shl ax, cl les bx, 9EC2h add bx, ax cmp es:bx+0Ch,2 ; only if level=0 or 1 jge invalid jmp strongest ;------------------------------------------------- ;bless: ;test bp-0Ah,4000h ; Not if Righteousness! ;jnz invalid ;jmp prefhero ;------------------------------------------------- maxdef: mov al, es:bx+5 cbw sal al,4 ; +16 point per defense add dx,ax jmp strongest ;------------------------------------------------- berserk: mov al, es:bx+5 cbw sal al,1 ; -2 point per defense add dx,ax neg dx ; Negate gate bonus as well atkbuff: mov al, es:bx ; melee mov bl, es:bx+0Dh ; figures imul bl ; highest melee*figure! add dx,ax jmp done ;------------------------------------------------- prefranged: mov al, es:bx+1 cbw sal al,4 ; +16 point per ranged attack strength add dx,ax jmp strongest ;------------------------------------------------- guardian: test byte ptr es:bx+18h,4 ; Missile Immunity jnz invalid prefhero: mov ax, es:bx+30h mov cl, 5 shl ax, cl les bx, 9EC2h add bx, ax ''cmp byte ptr bx+06h,0FFh ; shouldn't that be es:? <--------------------'' jle strongest add dx,60 ; +60 priority if hero strongest: push dx push di db 9Ah,2Ah,00,58h,04h pop cx pop dx add dx,ax jmp done invalid: mov dx,0FFC0h done: pop si retn Edit : both immolation and true sight are already implemented outside in CoM but if you have the space you probably want it done inside for the RC. At first sight the most obvious differences seem the need to uncomment righteousness and berserk. Combat Spell Lock is not a thing in CoM, but it is in the RC for that you likely want the target with most existing enchantments. Everything else looks good as is. :Hey, it's the unused Disintegrate target picker! =P Questions, questions, questions. Whenever you have a few minutes =) # With Spell Lock, I'd assume the Gate Bonus shouldn't apply, but should targeting be based solely on the amount of enchantments and no other factors? I mean I could do something like 2 or 4 per enchant, maybe some extra for fantastic units if the opponent plays blue or white (not sure how I would query that yet though), but then branch into strongest too? Or would that create too much of a bias? I don't know how big the range of that evaluation result is. # Is the code I see in the executable a direct result of the above input into your assembler? Specifically, the "sal al, 4" turned into 4 consecutive "shl al, 1" instructions bothers me somewhat. # Do you want the above code to be a bit more optimized in terms of space, or are you happy with it as it is? # Do you want me to keep this setup for the RC or can I do some of the stuff from my previous question there? E.g., I found this to be a more optimal entry setup, and it would also work with your current CoM version because it no longer actually uses the enchant flags in this function, and there's enough space before both calls for setting ax: ; in : ; di = battle unit ID ; ax = spell id ; cx = enchantments low (don't need for CoM) ; dx = enchantments high (don't need for CoM) ; out : ; dx = priority On a side note, would you mind if I archived some of the older sections/headings of your talk page (i.e. move them to a separate page that I link to at the top)? Drake178 (talk) 21:22, July 7, 2019 (UTC) 1. Maybe looking at the overland version can give you some ideas, but that's about it, yes. Extra for fantastic units sounds good too, enemy realms are stored in $9298-92a2, see the function at $BBCCC which fills them. I'd scale this half of the priority based on the amount of resistance missing to be mostly invicible if there is room for that and the other half by number of enchants on the unit. I'd also consider things with not enough spells and not fantastic with vulnerable resistance an invalid target because it's a waste to cast it in that case. However this sum of priority would then be scaled (multipled) by the cost of the unit - it's meaningless to protect something that's not a relevant unit. Gate bonus should probably stay but only if the target is otherwise having a reasonable priority. Ultimately this is entirely up to how much effort you want to put into it, Spell Lock isn't exactly the most important or fun spells in the game. 2. Yes. (well, not the same version, the posted one is the newer CoM one) There is no shl al,4 instruction for the x86 CPU, only sal al,cl but that requires loading 4 into cl. I can't use that if I use cx. I don't think this is an assembler bug although I've seen it generate other bugs before (it doesn't like jumps over $8000 distance and pushing immediate bytes over $80, I think that's all I ever had problems with). ::Huh? Why would you be coding for a 8086 when the game requires a 386+? EDIT: oh my, that just made me realize why the borland compiler did it that way... Anyway, SHL AL, 4 (C0 E0 04) is perfectly valid from the 80286, and you're free to use it in your code. I know it works because I'm using SHL R16, IMM8 quite a lot, and that was introduced in the same processor. Both DOSBox and IDA understand it without issues. ::Drake178 (talk) 23:58, July 7, 2019 (UTC) ::It does? I don't remember seeing that in the game's readme files but ofc that doesn't mean it's not true. I saw no use of eax anywhere so I assumed it isn't for 386. I guess 286 is still a step above x86 though and that definitely is required due to memory, but I was happy to find any working assembler at all, even that took quite some searching around. Although considering everyone runs it on DOSBOX anyway, it's not like we do need to maintain 286 compability, not sure why I even cared. Then again, this is the only working assembler I found so... I didn't have much choices to think about so I never did. SeravySensei (talk) 00:30, July 8, 2019 (UTC) :Well, by the looks of it, the game was actually compiled with the default option of BC 3.1, which is to generate 8086 code. What a shame. The manual says on the first page that an 80386sx is required. Which kind of makes sense, since unless you had a hardware EMS board, you needed a 386 to have EMS. It doesn't matter that much though, with 16bit default addressing the only practical use of the 32bit registers that I see would be some bitflags, so an operand size prefix would probably not be worth the hassle. I'll stick with the 16bit code too, but things like the above SHL AL, 4 or, more importantly, an IMUL DI, 6Eh can be immensely useful =D Drake178 (talk) 01:17, July 8, 2019 (UTC) :EDIT: oh, for the record, I don't use an assembler, at least not the way you do. I just use this (that also messes up 16bit immediate pushes and long jumps by wanting to operand-size prefix them, so those I do manually). Drake178 (talk) 01:20, July 8, 2019 (UTC) 3. Up to you, I'm not modifying RC code myself unless it's exceptional, I only add the patches. If you think you are going to need the space in the future, sure, otherwise there is no point. 4. You can do it however you find more convenient as long as is functionally equivalent or preferably, superior. Sure, you can move them. This whole wiki talk stuff is kinda alien and chaotic to me, forum threads and posts make more sense then editing the same "post" for everything... SeravySensei (talk) 21:58, July 7, 2019 (UTC) AI Banish (shelved for now) :* Next one: Fixes bug: AI can waste Mana/Skill on Banish Because it's adjusting the extra to a random multiple of 5 instead of 15, which is what actually grants a benefit. Will produce a warning without W126, which it also functionally supercedes (can't reverse it any more, have to do so at $8367E instead of $8369E). v1.31 - v1.51 (WIZARDS.EXE) ; swap the Counter Magic and Banish checks 8367D 40 30 ; skip the first check instead of the second in v1.50+ ; (remove this one byte for a v1.31 patch) 8367E 75 EB ; swap the Counter Magic and Banish checks 8369D 30 40 8369E EB 75 ; use increments of 15 instead of 5 for Banish 836A3 05 0F 836B2 05 0F Drake178 (talk) 17:17, June 18, 2019 (UTC) For this one, we probably should make the AI spend the optimal amount instead of at random? No idea how much that is though, slider spells are not really a thing in CoM. But it should depend on the effective resistance of the target against the spell. It should lean towards spending more for a "faster" success but should avoid wasteful spending (Definitely avoid over 100%, boost below 50%, not sure in-between though). SeravySensei (talk) 15:06, July 4, 2019 (UTC) :I'll do some brainstorming on this, I've made loads of placeholder far calls and an extreme amount of space in that function, so anything goes really. Might check if I can retrieve the result of the original target picker that resulted in the spell being selected, or more likely just redo it and base a decision on that. In that case though, it may be worth doing the same for some other slider spells too, like Life Drain and direct damage. Drake178 (talk) 22:08, July 6, 2019 (UTC) Dispel vs Control Change I saw the question come up on RB, so here's how I think that should work, from some time ago. Sorry I didn't post it for you before for discussion: User_blog:Drake178/Dispel_Magic_Patch Drake178 (talk) 15:58, September 22, 2019 (UTC) :Now that I think about it, I probably messed up that patch and forgot to add an exclusion for when a player already has 9 units, in which case dispelling the control change should no longer be possible. If that's the case I'll have to rewrite it. Still, I think the logic should ultimately be the same. Confusion's control change should not affect which spells are getting targeted by dispels at all, and for Possession and Creature Binding, dispelling them should be evaluated before removing any beneficial spells. Although, this latter is of course arguable, since there is no real way of knowing who the original caster is, unless they are overland-casts. To me, it seems better to assume that they belong to the original owner of the unit since that's more straightforward to work with, but that also means that I should ideally make sure that tha AI won't buff such a unit, expecting the control change to be possibly removed. Drake178 (talk) 15:35, September 23, 2019 (UTC) I think I already decided I don't want Possession and Creature Binding to become dispellable in CoM...not 100% sure but I tbelieve I would remember if I wanted them to be possible to dispel. You are correct in assuming the mod is balanced around the idea that they can't be dispelled, they are more expensive than the equivalent "kill unit" spells which imples the unit dies. Dispelling them is rather meaningless in my opinion either way because possessed units tend to suicide attack the nearest thing immediately and get badly damaged or die anyway, leaving nothing to dispel. In the RC, the original intent is obvious : the spells can be dispelled but it fails to return control of the unit so that's a bug to fix. The base game's philosophy is pretty much "everything can be dispelled" so there is no doubt about that. What should happen to other spells on such units is pretty much undefined and we have no way to find out the original intentions.That means, anything goes. I guess assuming buffs on a control changed unit belong to you and not dispelling any does make sense. In CoM this isn't so simple because control change effects except Confusion cannot be dispelled. So not allowing control changed units to lose buffs also means you can't dispel units Possessed from you - they remain buffed until the end of battle no matter what. So in CoM that should likely be restricted to Confusion only, when it has the control change effect on. Which means two changes, first, dispelling stuff needs to be entirely skipped until the Confusion part if there is a type 2 confusion and second, if a type 2 confusion was present then it needs to continue from "dispel enemy curses on unit" instead of doing nothing else - if I want to be generous and allow that. However it would be a logical contradiction not to : Confusion is an enemy curse on your unit so if you can dispel it, that also means you can dispel the other curses simultaneously. CoM's AI already considers units with very harmful curses on as invalid targets for most spells especially buffs - I hope Confusion is included in that - but for the RC you'll need to add that if you want the functionality. If you do, I recommend excluding all units with any curses that render the unit useless, Sleep being the most obvious. Stasis isn't a thing in combat in the RC, but Shatter is probably bad enough to avoid buffing the unit as well. SeravySensei (talk) 16:15, September 23, 2019 (UTC) :For Confusion, I went with the simple solution of swapping branches if it's a type 2. While unlikely, I couldn't completely rule out the scenario where you'd want to dispel a buff from an enemy unit that you're controlling for the turn. Like, say, you want to suicide it, but it's Invulnerable. Or something like that. This also fixes both problems in one go, curses on your own unit still get targeted, and buffs do not. It's also easy to do if you have space anywhere in the segment, since you can just jump out and test the condition before starting the dispel effect loop. :Speaking of which, I can probably resolve my 9 unit mistake with a jump as well. If so, would you consider this patch for the RC provided I resolve the AI buff targeting? That'd fall in with the already open topic above anyway, that's also waiting on action on my part. I've just been putting it off to get to the end of the combat code. Also, are there any other additions or changes you'd want to make to the dispel logic? Drake178 (talk) 20:42, September 23, 2019 (UTC) As far as I remember I was against fixing the 9 unit issue that way (preventing the casting of, and consequently, dispelling of, control changing spells), so if I do include it for the RC, it has to be without that. Also, for the RC, my preferred soltuion would be to either always, or never dispel other buffs but always dispel other curses, regardless of the result of the first dispel attempt. The reason is simple, if I fail the first dispel but succeed the second, why should I be losing the enchantments in between the two? It's also not logical - the dispel is attempting to remove the spells simultaneously so the targeted spells can't depend on the success - that's a time paradox. So if we do take the player-friendly and intuitive path, it should be taken all the way, and not dispel the buffs, regardless of dispelling the possession. It should in that case, also include this fact in the possession icon when right clicked but I can add that into HELP.LBX myself. So my preferred solution for the RC is basically : Owned and controlled unit : dispel Curses only. Owned but enemy controlled unit : dispel Curses only (including the control changing curse, order does not matter). Not owned but controlled unit : dispel buffs (for consistency, and because dispelling curses would dispel my own possession. I can see this not being intuitive for players though and ending up dispelling buffs when they want to dispel something like black sleep from the possessed unit.) Enemy owned and controlled unit : dispel buffs. ...so from the looks of it, this is a fairly simple implementation, if the unit is control-changed, execute the opposing branch than normally, for all 3 possible control changing effects. In fact, it's the exact same thing I'll do for CoM,except in CoM it's limited to Confusion only as the other two can't be dispelled anyway so units suffering from it can safely be considered permanently enemy owned units. SeravySensei (talk) 21:28, September 23, 2019 (UTC) :The 9 units fix is going to be optional either way, it's more the rest of your take that I was interested in. I didn't consider removing the enchantments between two dispel attempts of the same control change, that's a good point, I can roll with your version there, although it kind of goes against the original spirit of everything being dispellable. But then the other option is to remove both the buffs and the control change, which is not so friendly. Hmm. Maybe the control change itself should remove the buffs to begin with? But then you might not want to dispel it any more anyway. Also, for not owned but controlled units, I'd still prefer removing curses, except in the case of Confusion, but I can probably come up with a way to make that optional too. Drake178 (talk) 22:52, September 23, 2019 (UTC) Removing curses means removing Possession/Creature Binding and giving back control of the unit to the enemy. Or, you have to accept the inconsitency that curses don't all get removed and you get to keep those two. You can't even say it's because those are yours - the other curses might be yours as well, if you used them before the Possession. That inconsistency is on top of the fact units you control but don't own reverse what gets dispelled, while the opposite does not. I don't particularly like that but I see why you prefer it - it's the most benefitial assuming the more likely case of the AI not dispelling the possession....or is it the more likely case? I mean it's not a very high cost spell and if the unit is worth anything the AI really should put significant effort into dispelling it and get it back. The save modifier is much worse than in CoM so in general dispelling trumps the chance of the human player succeeding at casting it again next turn. SeravySensei (talk) 00:03, September 24, 2019 (UTC) :Well, the discrepancy was already created by the devs when they decided to do selective dispelling. None of the sources that I know to have inspired MoM's magic system have that. You either target a specific effect, or you go all in, no discrimination. IIRC D&D doesn't even allow your own spells to resist an area cast, so you always have to sacrifice them. MtG doesn't have dispel resistance in the first place. Disenchant-type magic is typically designed to turn the table on an opponent with an overwhelming magical advantage, not selectively try to remove just the magic that is harmful to you. :Given that, I also don't think that the concept was to remove only the spells cast by the opponent, but rather to only target those that are not beneficial to the caster. Of course, we'll probably never know for sure, but this seems much more likely to me. And if that's the case, then removing curses from a not owned but controlled unit is more in line with the initial intent. I think that incosistency is actually insignificant compared to the one already presented by the selective dispelling. If I was writing a mod, I don't think I'd allow that in the first place. Or it would be something much more rare and unique than the "generic" stuff. But I think there's also a technical side of this story. Being able to select a specific effect to dispel might be a pain in terms of UI design. Drake178 (talk) 15:26, September 24, 2019 (UTC) For v1.52 ; The AI is now able to recognize up to 200 targets per continent instead of 25 for land based attacks. E7D58 83 81 E7D5C 19 C8 E7D5D 7D 00 E7D5E 38 7D E7D5F 8B 27 E7D60 1E B8 E7D61 92 08 E7D62 90 00 E7D63 D1 F7 E7D64 E3 2E E7D65 8B 92 E7D66 46 90 E7D67 06 BB E7D68 89 66 E7D69 87 7A E7D6A 5E 03 E7D6B 90 D8 E7D6D 1E 46 E7D6E 92 06 E7D6F 90 89 E7D70 D1 07 E7D71 E3 8B E7D72 8B 46 E7D73 46 08 E7D74 08 89 E7D75 89 47 E7D76 87 02 E7D77 2C 8B E7D78 90 46 E7D79 8B 0A E7D7A 1E 89 E7D7B 92 47 E7D7C 90 04 E7D7D D1 8B E7D7E E3 46 E7D7F 8B 0C E7D80 46 89 E7D81 0A 47 E7D82 89 06 E7D83 87 FF E7D84 FA 06 E7D85 8F 92 E7D86 8B 90 E7D87 1E 90 E7D88 92 90 E7D8A D1 90 E7D8B E3 90 E7D8C 8B 90 E7D8D 46 90 E7D8E 0C 90 E7D8F 89 90 E7D90 87 90 E7D91 C8 90 E7D92 8F 90 E7D93 FF 90 E7D94 06 90 E7D95 92 90 E7E45 8B B8 E7E46 DE 08 E7E47 D1 00 E7E48 E3 F7 E7E49 83 EE E7E4A BF BB E7E4B C8 66 E7E4C 8F 7A E7E4D 00 03 E7E4E 7F D8 E7E4F 03 83 E7E50 E9 7F E7E51 DD 06 E7E53 8B 7F E7E54 DE 03 E7E55 D1 E9 E7E56 E3 D8 E7E57 8B 00 E7E58 87 8B E7E59 FA 47 E7E5A 8F 04 E7E60 BB B9 E7E65 FB F9 E7E69 7C 7E E7E6E B8 53 E7E6F 3C 6A E7E70 00 3C E7E71 50 FF E7E72 FF 76 E7E73 76 08 E7E74 08 FF E7E75 FF 76 E7E76 76 06 E7E77 06 FF E7E78 8B 77 E7E79 DE 02 E7E7A D1 FF E7E7B E3 37 E7E7C FF 90 E7E7D B7 90 E7E7E 2C 90 E7E80 8B 90 E7E81 DE 90 E7E82 D1 90 E7E83 E3 90 E7E84 FF 90 E7E85 B7 90 E7E86 5E 90 E7E9E 8B 5B E7E9F DE 8B E7EA0 D1 47 E7EA1 E3 06 E7EA3 87 C8 E7EA4 C8 99 E7EA5 8F F7 E7EA6 8B 7E E7EA7 C8 F2 E7EA8 99 40 E7EA9 F7 83 E7EAA 7E F9 E7EAB F2 01 E7EAC 40 7F E7EAD 83 09 E7EAE F9 83 E7EAF 01 7E E7EB0 7F F2 E7EB1 09 05 E7EB2 83 7E E7EB3 7E 03 E7EB4 F2 B8 E7EB5 05 FF E7EB6 7E FF E7EB7 03 89 E7EB8 B8 46 E7EB9 FF F4 E7EBA FF 3B E7EBB 89 46 E7EBC 46 F8 E7EBD F4 7E E7EBE 90 71 E7EBF 90 FF E7EC0 90 76 E7EC1 90 EC E7EC2 90 FF E7EC3 3B 76 E7EC4 46 FE E7EC5 F8 FF E7EC6 7E 76 E7EC7 68 FE E7EC8 83 6A E7EC9 7E 01 E7ECA EA 6A E7ECB 00 01 E7ECC 74 68 E7ECD 54 F0 E7ECE FF C5 E7ECF 76 68 E7ED0 EC 68 E7ED1 FF C6 E7ED2 76 68 E7ED3 FE E0 E7ED4 FF C6 E7ED5 76 FF E7ED6 FE 76 E7ED7 B8 EE E7ED8 04 FF E7ED9 00 77 E7EDA 50 02 E7EDB B8 FF E7EDC 01 37 E7EDD 00 FF E7EDE 50 76 E7EDF B8 08 E7EE0 F0 FF E7EE1 C5 76 E7EE2 50 06 E7EE3 B8 33 E7EE4 68 C0 E7EE5 C6 50 E7EE7 B8 50 E7EE8 E0 50 E7EE9 C6 50 E7EEB FF 90 E7EEC 76 90 E7EED EE 90 E7EEE 8B 90 E7EEF DE 90 E7EF0 D1 90 E7EF1 E3 90 E7EF2 FF 90 E7EF3 B7 90 E7EF4 2C 90 E7EF6 8B 90 E7EF7 DE 90 E7EF8 D1 90 E7EF9 E3 90 E7EFA FF 90 E7EFB B7 90 E7EFC 5E 90 E7EFE FF 90 E7EFF 76 90 E7F00 08 90 E7F01 FF 90 E7F02 76 90 E7F03 06 90 E7F04 33 90 E7F05 C0 90 E7F06 50 90 E7F07 33 90 E7F08 C0 90 E7F09 50 90 E7F0A 33 90 E7F0B C0 90 E7F0C 50 90 E7F0D 33 90 E7F0E C0 90 E7F0F 50 90 E7F10 33 90 E7F11 C0 90 E7F12 50 90 E7F13 33 90 E7F14 C0 90 E7F15 50 90 E7F44 8B B8 E7F45 5E 08 E7F46 F6 00 E7F47 D1 F7 E7F48 E3 6E E7F49 8B F6 E7F4A 87 BB E7F4B 5E 66 E7F4C 90 7A E7F4D 8B 03 E7F4E 5E D8 E7F4F 0A 8B E7F50 89 7E E7F51 07 0A E7F53 5E 07 E7F54 F6 89 E7F55 D1 05 E7F56 E3 8B E7F57 8B 47 E7F58 87 02 E7F59 2C 8B E7F5A 90 7E E7F5B 8B 0C E7F5C 5E 89 E7F5D 0C 05 E7F5E 89 C7 E7F5F 07 47 E7F60 8B 06 E7F61 5E 01 E7F62 F6 00 E7F63 D1 90 E7F64 E3 90 E7F65 C7 90 E7F66 87 90 E7F67 C8 90 E7F68 8F 90 E7F69 01 90 E7F6A 00 90 I've recently upgraded my patch bytes generator to do just this =P I'll send it your way when I get a chance ;) Drake178 (talk) 01:14, January 15, 2020 (UTC) ---- ---- Fixes bug: the world generator doesn't use every intended tundra graphic Because of a mistyped case check. All versions (MAGIC.EXE) 3BAED 04 02 Drake178 (talk) 01:34, January 26, 2020 (UTC) ---- ---- Fixes bug: minerals can spawn on grasslands Or, to be more precise: hills with diagonally adjacent other hills but no cardinally adjacent ones are converted incorrectly into grasslands instead of the intended single tile hills. All versions (MAGIC.EXE) ; test for connections from a register instead 3B6F0 83 8B 3B6F1 7E 5E 3B6F2 FA FA 3B6F3 00 85 3B6F4 7E DB 3B6F5 34 7E 3B6F6 8B 33 ; get the tile type index from the conversion matrix 3B6F7 46 D1 3B6F8 FA E3 3B6F9 D1 03 3B6FA E0 5E 3B6FB 8B F6 3B6FC 5E 8B 3B6FD F6 87 3B6FE 03 00 3B6FF D8 02 ; check if it's the single tile mountain type 3B700 8B 3C 3B701 87 A4 ; skip conversion if it is 3B702 00 74 3B703 02 26 Code: $3B6F0: 8b 5e fa mov bx, bp-6 //Tile_Border_Flags 85 db test bx, bx 7e 33 jle +51 d1 e3 shl bx, 1 03 5e f6 add bx, bp-10 //TERRTYPE_Pointer 8b 87 00 02 mov ax, bx+0x200 // record 2 3c a4 cmp al, 0xa4 74 26 jz +38 Drake178 (talk) 01:34, January 26, 2020 (UTC) ---- ---- Fixes bug: heroes with no ranged magical attacks can get arcane power Fixes bug: heroes eligible for arcane power are not always eligible for the super version, and will simply lose their picks when they roll it Obsoletes and replaces IM200. Because I'm not happy with the band-aid solution that requires further editing if one wants to customize the default hero profiles. It will generate one warning when applied with IM200 (for $4801D), but I'd recommend reversing that first anyway. v1.31 - v1.52 (MAGIC.EXE) ; check for ranged attacks before regular Arcane Power 4801A 83 EB 4801B 7E 14 4801C FC 90 4801D 1E 90 ; don't exclude lightning type attacks 4803E 1F 1E ; skip all processing if the hero is not eligible 48040 31 47 48051 20 36 ; branch based on the presence of the regular ability 48058 83 A9 48059 F2 04 4805B 35 75 4805C 04 1E 4805D 00 35 4805E 89 0C 4805F 46 00 48060 F4 EB 48061 89 1C 48062 56 90 48063 F2 90 Drake178 (talk) 01:34, January 26, 2020 (UTC) ---- ---- Fixes bug: players can't cast overland spells on their first turn v1.31 - v1.51 (MAGIC.EXE) 46382 8B 89 46383 C6 BF 46384 BA 54 46385 C8 69 46386 04 90 46387 F7 90 46388 EA 90 46389 8B 90 4638A D8 90 Drake178 (talk) 01:34, January 26, 2020 (UTC) ---- ---- Fixes bug: AI secondary realms are set wrong if their primary is Nature M475FIX for the AI wizards. For the record, single realm wizards did set it right all along, so 475 didn't fix that particular issue as it was non-existent. 45F34 F6 FE 45F41 87 46 45F42 5A F8 45F43 69 90 45F46 FE F6 45F48 01 00 Drake178 (talk) 01:34, January 26, 2020 (UTC) ---- ---- I guess I'll jump on the help file now, everything else is on hold until I'm finished with that. And the next e-mail I send you probably won't be in English =P Drake178 (talk) 12:34, February 12, 2020 (UTC)